package ay.shadow.nacos.config;

import com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
import lombok.Builder;
import lombok.Data;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;

import static com.alibaba.nacos.api.PropertyKeyConst.*;

@Component
public class NacosServiceDiscoveryV2 extends NacosServiceDiscovery {

    // 可以直接配置对应service
//    public static final Map<String, ServiceInstance> SERVICE_INSTANCE_MAP = new ConcurrentHashMap<>();
    // 服务名 对应 命名空间 或者
    public static final Map<String, GroupAndNamespace> SERVICE_INSTANCE_MAP = Map.of(
            "shadow-stock", GroupAndNamespace.builder().groupName("STOCK").namespace("stock-server").build()
            ,"shadow-order", GroupAndNamespace.builder().groupName("ORDER").namespace("order-server").build()
            );

    @Data
    @Builder
    public static class GroupAndNamespace {
        private String groupName;
        private String namespace;
    }


    public NacosServiceDiscoveryV2(NacosDiscoveryPropertiesV2 discoveryProperties, NacosServiceManagerV2 nacosServiceManager) {
        super(discoveryProperties, nacosServiceManager);
        this.discoveryProperties = discoveryProperties;
        this.nacosServiceManager = nacosServiceManager;
        this.nacosServiceManager.setNacosDiscoveryProperties(this.discoveryProperties);
        this.newGroupName = discoveryProperties.getGroup();
    }

    private final NacosDiscoveryPropertiesV2 discoveryProperties;
    private final NacosServiceManagerV2 nacosServiceManager;
    private String newGroupName;
    private String newNamespace;

    // 重写该方法
    @Override
    public List<ServiceInstance> getInstances(String serviceId) throws NacosException {
        String group = this.discoveryProperties.getGroup();
        // 优先保证同分组下的服务调用
        NamingService namingService = this.namingService();
        List<Instance> instances = namingService.selectInstances(serviceId, group, true);
        if (instances.isEmpty()) {
            // 获取动态自定义服务
            instances = getGroupAndSpace(serviceId).getAllInstances(serviceId, newGroupName, true);
        }
        return hostToServiceInstanceList(instances, serviceId);
    }

    @Override
    public List<String> getServices() throws NacosException {
        ListView<String> services = namingService().getServicesOfServer(1, Integer.MAX_VALUE, newGroupName);
        return services.getData();
    }

    private NamingService namingService() {
        return nacosServiceManager.getNamingService();
    }

    private NamingService getGroupAndSpace(String serviceId) {
        GroupAndNamespace groupAndNamespace = SERVICE_INSTANCE_MAP.get(serviceId);
        if (groupAndNamespace != null) {
            newGroupName = groupAndNamespace.getGroupName();
            newNamespace = groupAndNamespace.getNamespace();
            // 获取对应的NamingService
           return nacosServiceManager.createNewNamingService(getNacosProperties());
        }
        return nacosServiceManager.getNamingService();
    }

    // 配置Properties
    public Properties getNacosProperties() {
        Properties properties = new Properties();
        properties.put(SERVER_ADDR, discoveryProperties.getServerAddr());
        properties.put(USERNAME, Objects.toString(discoveryProperties.getUsername(), ""));
        properties.put(PASSWORD, Objects.toString(discoveryProperties.getPassword(), ""));
        properties.put(NAMESPACE, newNamespace);
        properties.put(UtilAndComs.NACOS_NAMING_LOG_NAME, discoveryProperties.getLogName());

        if (discoveryProperties.getEndpoint().contains(":")) {
            int index = discoveryProperties.getEndpoint().indexOf(":");
            properties.put(ENDPOINT, discoveryProperties.getEndpoint().substring(0, index));
            properties.put(ENDPOINT_PORT, discoveryProperties.getEndpoint().substring(index + 1));
        } else {
            properties.put(ENDPOINT, discoveryProperties.getEndpoint());
        }

        properties.put(ACCESS_KEY, discoveryProperties.getAccessKey());
        properties.put(SECRET_KEY, discoveryProperties.getSecretKey());
        properties.put(CLUSTER_NAME, discoveryProperties.getClusterName());
        properties.put(NAMING_LOAD_CACHE_AT_START, discoveryProperties.getNamingLoadCacheAtStart());

        discoveryProperties.enrichNacosDiscoveryProperties(properties);
        return properties;
    }
}

